﻿using AntdUI;
using System.Runtime.CompilerServices;
using WenAntdUI.Settings;

namespace WenAntdUI;

/// <summary>
/// 全局参数
/// </summary>
public class AppConfig : INotifyPropertyChanged
{
    private static AppConfig? config;

    /// <summary>
    /// 全局设置
    /// </summary>
    public static AppConfig Config => config ??= new AppConfig();

    /// <summary>
    /// 当属性值更改时发生。 Occurs when a property value changes.
    /// </summary>
    /// <remarks>此事件通常用于通知订阅者属性值已更新。它通常在支持数据绑定或需要发出属性更改信号的类中实现
    /// values.</remarks>
    public event PropertyChangedEventHandler? PropertyChanged;

    /// <summary>
    /// 获取或设置全局设置内容
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    public object? this[string key]
    {
        get
        {
            // 先查找属性
            var prop = GetType().GetProperty(key);
            if (prop != null)
            {
                return prop.GetValue(this);
            }
            // 再查找字段
            var field = GetType().GetField(key);
            if (field != null)
            {
                return field.GetValue(this);
            }
            // 最后查找 Custom
            return Custom.TryGetValue(key, out var value) ? value : null;
        }
        set
        {
            // 先查找属性
            var prop = GetType().GetProperty(key);
            if (prop != null && prop.CanWrite)
            {
                prop.SetValue(this, value);
                return;
            }
            // 再查找字段
            var field = GetType().GetField(key);
            if (field != null)
            {
                field.SetValue(this, value);
                return;
            }
            // 最后写入 Custom
            SetCustom(key, value);
        }
    }

    /// <summary>
    /// 属性变更通知
    /// </summary>
    /// <param name="propertyName"></param>
    public void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private Dictionary<string, object?>? custom;
    /// <summary>
    /// 全局设置
    /// </summary>
    public Dictionary<string, object?> Custom => custom ??= [];

    /// <summary>
    /// 获取自定义设置
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <returns></returns>
    public T? GetCustom<T>(string key) where T : class =>
        Custom.TryGetValue(key, out var value) && value is T t ? t : default;

    /// <summary>
    /// 存储自定义设置
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <param name="value"></param>
    public void SetCustom<T>(string key, T? value) where T : class, new()
    {
        if (!Custom.TryGetValue(key, out var oldValue) || !Equals(oldValue, value))
        {
            Custom[key] = value;
            OnPropertyChanged(nameof(Custom));
        }
    }

    private Color themeColor = Style.Get(Colour.Primary);


    /// <summary>
    /// 主题颜色
    /// </summary>
    public Color ThemeColor
    {
        get => themeColor;
        set
        {
            if (themeColor != value)
            {
                themeColor = value;
                AppSettings.Set("ThemeColor", value);
                OnPropertyChanged(nameof(ThemeColor));
            }
        }
    }

    private bool? isDark;
    /// <summary>
    /// 皮肤样式
    /// </summary>
    public bool IsDark
    {
        get => isDark ?? false;
        set
        {
            if (isDark != value)
            {
                isDark = value;
                AntdUI.Config.IsDark = value;
                AppSettings.Set("ThemeDark", isDark);
                IsDarkChanged?.Invoke(this, value);
                OnPropertyChanged(nameof(IsDark));
            }
        }
    }

    /// <summary>
    /// 皮肤样式
    /// </summary>
    public static bool Dark => Config.IsDark;

    /// <summary>
    /// 皮肤样式改变事件
    /// </summary>
    public event EventHandler<bool>? IsDarkChanged;

    /// <summary>
    /// 
    /// </summary>
    public int MenuSplitterDistance
    {
        get
        {
            return AppSettings.GetOrSet(nameof(MenuSplitterDistance), (int)(210 * AntdUI.Config.Dpi), "菜单栏宽度", "系统设置");
        }
        set
        {
            AppSettings.Set(nameof(MenuSplitterDistance), value, "菜单栏宽度", "系统设置");
        }
    }

    /// <summary>
    /// 菜单栏是否收缩
    /// </summary>
    public bool IsMenuCollapsed
    {
        get
        {
            return AppSettings.GetOrSet(nameof(IsMenuCollapsed), false, "菜单栏收缩", "系统设置");
        }
        set
        {
            AppSettings.Set(nameof(IsMenuCollapsed), value, "菜单栏收缩", "系统设置");
        }
    }
}
